package travianBot.botScripts;

import java.io.IOException;
import java.util.HashMap;

import org.apache.log4j.Logger;
import org.htmlcleaner.HtmlCleaner;
import org.htmlcleaner.TagNode;
import org.htmlcleaner.XPatherException;

import travianBot.TravianBot;
import travianBot.TravianBotException;

public class BuildingScript extends TravianScript {

	String[] 	resourceArray;
	int[]		levelArray;
	static Logger log=Logger.getLogger(BuildingScript.class);
	
	public static final String BUILD_VILLAGE_HISTORY = "BuildingScript.village_history";
	
	public BuildingScript(String csvLine){
		init(csvLine);
	}
	
	public void init(String csvLine){
		String[] tokens = csvLine.split(",");
		
		int cursorToken 		= Integer.parseInt(tokens[0]);
		String villageNameToken = tokens[1];
		String typeToken 		= tokens[2];
		
		this.cursorPosition = cursorToken;
		this.villageName = villageNameToken;
		this.type = typeToken;
		
		// collect the remaining entries
		int tailLength = tokens.length - 3;
		
		String[] localResourceArray 		= new String[tailLength];
		int[] 	localResourceLevelArray 	= new int[tailLength];
		
		// collect the tail which is variable length
		String[] resourcePieces;
		String   resource;
		int      level;
		for (int i = 3; i < tokens.length; i++) {
			resourcePieces = tokens[i].split(":");
			localResourceArray[i-3]=resourcePieces[0];
			
			if(resourcePieces.length > 1){
				level = Integer.parseInt(resourcePieces[1]);
			}else{
				level = -1;
			}
			localResourceLevelArray[i-3] = level;
		}
		log.debug("creating resource script from: "+csvLine);
		log.debug("creating resource using tokens: "+cursorToken+","+villageNameToken+","+typeToken+","+localResourceArray+","+localResourceLevelArray);
		
		this.resourceArray = localResourceArray;
		this.levelArray = localResourceLevelArray;
	}
	
	/**
	 * tidyup method to clean up the session.
	 * Normally used to reset the session before starting a complete script run
	 * @param sessionInfoMap
	 */
	public void initialiseSession(HashMap<String,String> sessionInfoMap){
		sessionInfoMap.remove(BUILD_VILLAGE_HISTORY);
	}
	
	public void runScript(TravianBot travianBot, HashMap<String,String> sessionInfoMap ) throws TravianBotException{
		// if we have run a build script against this village already, don't run another one
		if(!isVillageInBuildHistory(this.villageName, sessionInfoMap)){
			if(!this.scriptExhausted){
				int upgradeResult = travianBot.upgradeBuilding(this.villageName, getCurrentResourceUpgrade(), getCurrentResourceLevel());
				incrementResourceUpgradecounter();
				int counter = 1;
				
				while((upgradeResult == TravianBot.BUILD_FAILED || upgradeResult == TravianBot.BUILD_REACHED_LEVEL) && this.resourceArray.length > counter){				
					upgradeResult = travianBot.upgradeBuilding(this.villageName, getCurrentResourceUpgrade(), getCurrentResourceLevel());
					incrementResourceUpgradecounter();
					counter++;
				}	
				
				if((upgradeResult == TravianBot.BUILD_REACHED_LEVEL ) && counter == this.resourceArray.length){
					this.scriptExhausted = true;
					log.info("Build script for "+this.villageName+" is exhausted.  No longer running it");					
				}
				
				// if we have succeeded in running something, mark that we don't want any other build 
				// scripts run against this village
				if(upgradeResult == TravianBot.BUILD_PASSED || upgradeResult == TravianBot.BUILD_NOT_READY){
					addVillageToBuildHistory(this.villageName, sessionInfoMap);
				}
			}else{
				log.info("Build script for "+this.villageName+" is exhausted.  No longer running it");
			}
		}else{
			//log.info("A build script has already been run against village:"+this.villageName);
		}
	}
	
	private void addVillageToBuildHistory(String villgeName, HashMap<String,String> sessionInfoMap){
		String buildHistory = sessionInfoMap.get(BUILD_VILLAGE_HISTORY);
		if(buildHistory != null){
			buildHistory += ","+villgeName;
			sessionInfoMap.put(BUILD_VILLAGE_HISTORY, buildHistory);
		}else{
			buildHistory = villgeName;
			sessionInfoMap.put(BUILD_VILLAGE_HISTORY, buildHistory);
		}
	}
	
	private boolean isVillageInBuildHistory(String villgeName, HashMap<String,String> sessionInfoMap){
		boolean  returnBool = false;
		String buildHistory = sessionInfoMap.get(BUILD_VILLAGE_HISTORY);
		if(buildHistory != null){
			String[] historyArray = buildHistory.split(",");
			
			for (int i = 0; i < historyArray.length; i++) {
				String historyVillage = historyArray[i];
				if(historyVillage.equals(villgeName)){
					returnBool = true;
					break;
				}
			}
		}
		return returnBool;
	}
	
	public static String getNewBuildLink(String htmlContent, String building) throws TravianBotException{
		HtmlCleaner htmlCleaner = new HtmlCleaner();
		String returnString = null;
		try {
			TagNode node = htmlCleaner.clean(htmlContent);
			Object[] nodeArray = node.evaluateXPath("//div[@id='build']");
			TagNode h2Node = null;
			TagNode tempNode = null;
			
			if(nodeArray != null && nodeArray.length > 0){
				TagNode[] childNodeArray = ((TagNode)nodeArray[0]).getChildTags();
				
				//
				// walk through the child nodes to find the name in an h2,
				// followed by the link we need
				//
				for (int i = 0; i < childNodeArray.length; i++) {
					tempNode = (TagNode)childNodeArray[i];
					if(tempNode.getName().equals("h2") && 
							tempNode.getText().toString().equalsIgnoreCase(building)){																
						h2Node = tempNode;
						
						// get the table node
						tempNode = (TagNode)childNodeArray[i+1];
						// find the link
						Object[] linkNodeArray = tempNode.evaluateXPath("//a[@class='build']");
						if(linkNodeArray != null && linkNodeArray.length > 0){							
							TagNode linkNode = (TagNode)linkNodeArray[0];
							returnString = linkNode.getAttributeByName("href");
						}						
						break;
					}
				}
			}			
		} catch (IOException e) {
			e.printStackTrace();
			throw new TravianBotException("problems getting upgrade link", e);
		} catch (XPatherException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			throw new TravianBotException("xpath problems getting upgrade link", e);
		}
		return returnString;
	}
	
	public String getCurrentResourceUpgrade(){
		return resourceArray[cursorPosition];
	}
	
	public int getCurrentResourceLevel(){
		return levelArray[cursorPosition];
	}
	
	public void incrementResourceUpgradecounter(){
		cursorPosition = (cursorPosition + 1)% resourceArray.length;
	}
	
	public String[] getResourceArray() {
		return resourceArray;
	}
	public void setResourceArray(String[] resourceArray) {
		this.resourceArray = resourceArray;
	}
	public int[] getLevelArray() {
		return levelArray;
	}
	public void setLevelArray(int[] levelArray) {
		this.levelArray = levelArray;
	}		

}
